<!DOCTYPE html>
<html lang="en">

<!-- Head tag -->
<head><meta name="generator" content="Hexo 3.9.0">

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!--Description-->
    

    <!--Author-->
    
        <meta name="author" content="ck">
    

    <!--Open Graph Title-->
    
        <meta property="og:title" content="CK&#39;s blogs">
    

    <!--Open Graph Description-->
    

    <!--Open Graph Site Name-->
    <meta property="og:site_name" content="CK&#39;s blogs">

    <!--Type page-->
    
        <meta property="og:type" content="website">
    

    <!--Page Cover-->
    

    <meta name="twitter:card" content="summary">
    

    <!-- Title -->
    
    <title>page - CK&#39;s blogs</title>

    <!-- Bootstrap Core CSS -->
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" integrity="sha384-y3tfxAZXuh4HwSYylfB+J125MxIs6mR5FOHamPBG064zB+AFeWH94NdvaCBm8qnd" crossorigin="anonymous">

    <!-- Custom Fonts -->
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- Gallery -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.css" type="text/css" rel="stylesheet">

    <!-- Custom CSS -->
    <link rel="stylesheet" href="/blog/css/style.css">

    <!-- Google Analytics -->
    


</head>


<body>

<div class="bg-gradient"></div>
<div class="bg-pattern"></div>

<!-- Menu -->
<!--Menu Links and Overlay-->
<div class="menu-bg">
    <div class="menu-container">
        <ul>
            
            <li class="menu-item">
                <a href="/blog/">
                    Home
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/archives">
                    Archives
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/2019/09/04/本人简历/">
                    About
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/tags">
                    Tags
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/categories">
                    Categories
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/contact.html">
                    Contact
                </a>
            </li>
            
        </ul>
    </div>
</div>

<!--Hamburger Icon-->
<nav>
    <a href="#menu"></a>
</nav>

<div class="container">

    <!-- Main Content -->
    <div class="row">
    <div class="col-sm-12">

        <!--Title and Logo-->
        <header>
    <div class="logo">
        <a href="/blog/"><i class="logo-icon fa fa-cube" aria-hidden="true"></i></a>
        
            <h1 id="main-title" class="title">CK's blogs</h1>
        
    </div>
</header>

        <section class="main">
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/04/本人简历/">
                本人简历
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-04</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h2 id="个人简历"><a href="#个人简历" class="headerlink" title="个人简历"></a><strong>个人简历</strong></h2><h3 id="个人信息"><a href="#个人信息" class="headerlink" title="个人信息"></a><strong>个人信息</strong></h3><table>
<thead>
<tr>
<th>性 名： 陈凯</th>
<th>年     龄： 27</th>
<th>电 话： 15300217317</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>邮 箱: <a href="mailto:ck15300217317@gmail.com" target="_blank" rel="noopener">ck15300217317@gmail.com</a></td>
<td>工作经验：4年</td>
<td>现 居： 北京市昌平区</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><strong>求职意向</strong></td>
<td>工作地点：北京</td>
<td>期望月薪：面议</td>
<td>求职意向: Python全栈开发</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><strong>教育背景</strong></td>
<td>学校名称：大连东软信息学院</td>
<td>就读时间：2011.09-2015.07</td>
<td>专业：计算机应用技术</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h3 id="个人介绍"><a href="#个人介绍" class="headerlink" title="个人介绍"></a><strong>个人介绍</strong></h3><p>​    通过四年Python开发，参与设计并开发过多个项目，多次负责核心模块的开发，熟练掌握tornado框架，熟悉Docker操作，熟练使用镜像、容器、仓库及docker-compose和 docker-file对项目进行镜像打包，熟悉前端业务规范，掌握vue脚手架，熟悉响应式开发框架Bootstrap，熟悉微信小程序开发，熟练三方API接口调用，熟练使用Mysql、redis及Mongo数据库，熟练使用Scrapy框架，拥有丰富的爬虫与反爬经验，有优秀的学习能力和团队沟通能力。 </p>
<h3 id="专业技能"><a href="#专业技能" class="headerlink" title="专业技能"></a><strong>专业技能</strong></h3><p><strong>※</strong>后台框架:  <strong>Tornado</strong>、 <strong>Django</strong>、<strong>Flask</strong></p>
<p><strong>※</strong>爬虫技术：<strong>requests</strong>、<strong>Scrapy_redis</strong>、<strong>Crawlspider</strong>、Selenium</p>
<p><strong>※</strong>数据库：<strong>Mysql</strong>、<strong>Redis</strong>、<strong>MongoDB</strong></p>
<p><strong>※</strong>前端框架：<strong>Vue.js</strong>、<strong>Css</strong>、<strong>Html5</strong>、Bootstrap</p>
<p><strong>※</strong>Linux：<strong>Docker</strong>、<strong>Nginx</strong>、<strong>uWsgi</strong>、数据库主从部署(mysql/redis)      </p>
<p><strong>※</strong>其他：<strong>cerlery</strong>、<strong>Fastdfs</strong>、<strong>Redisearch</strong>、<strong>jwt</strong>、<strong>Rpc框架</strong>、<strong>Websocket</strong>、微信小程序及公众号开发等</p>
<p><strong>※</strong>外语：<strong>大学英语四级</strong>（能流畅阅读英文文档）</p>
<h3 id="工作经历"><a href="#工作经历" class="headerlink" title="工作经历"></a><strong>工作经历</strong></h3><p>2017年07 月   —   至今                  公司名称：北京钱方银通科技有限公司                                                                       </p>
<p>2016年04 月   —  2017年06月    公司名称：北京盛藏艺步品有限公司</p>
<p>2015年08 月   —  2016年04月    公司名称：北京跟谁学科技有限公司                                                                   </p>
<h3 id="项目经验"><a href="#项目经验" class="headerlink" title="项目经验"></a><strong>项目经验</strong></h3><h4 id="项目一："><a href="#项目一：" class="headerlink" title="项目一："></a><strong>项目一</strong>：</h4><p>​     钱方好近          北京钱方银通科技有限公司</p>
<h5 id="项目描述："><a href="#项目描述：" class="headerlink" title="项目描述："></a><strong>项目描述：</strong></h5><p>​         钱方好近是聚合支付,又称作”第四方支付”，解决商户与各个支付平台复杂的支付逻辑，统一支付码，一码多用，不通过现金结算即可按照商户需要展开个性化定制，利用与各第三方支付平台以及合作银行等的聚合，大大方便了客户面对支付复杂的问题  </p>
<h5 id="项目职责："><a href="#项目职责：" class="headerlink" title="项目职责："></a><strong>项目职责：</strong></h5><p>1、基于<strong>Tornado</strong>实现<strong>Restful</strong>风格的在线聚合支付接口，提供支付宝、京东和微信等三方平台登陆</p>
<p>3、 使用<strong>Mysql</strong>存储数据，配置主从热备，水平分表</p>
<p>3、使用<strong>Redis</strong>集群作为缓存介质，缓解数据库压力</p>
<p>4、采用<strong>Celery</strong>和Rabbitmq异步任务队列架构，同时配置自动化定时任务</p>
<p>5、使用<strong>Redisearch</strong>打造全文检索引擎，百万级数据可以达到单次检索10毫秒以内的速度。</p>
<p>6、利用<strong>FastDFS</strong>结合FastDHT实现用户上传文件的分布式去重存储</p>
<p>7、使用<strong>Supervisor</strong>对后台服务例如<strong>uwsgi</strong>和<strong>Gunicorn</strong>进行监控和操作，<strong>降低日常维护成本</strong></p>
<h4 id="项目二："><a href="#项目二：" class="headerlink" title="项目二："></a><strong>项目二：</strong></h4><p>​     跟谁学            北京跟谁学科技有限公司 </p>
<h5 id="项目描述：-1"><a href="#项目描述：-1" class="headerlink" title="项目描述："></a><strong>项目描述：</strong></h5><p>​         跟谁学是一家在线教育和课程学习平台，主打“万千名师，一搜即得”，服务阶段从小学到大学以及上班族一站式服务，从名师出发为用户提供各类课程在线学习服务。</p>
<h5 id="项目职责：-1"><a href="#项目职责：-1" class="headerlink" title="项目职责："></a><strong>项目职责：</strong></h5><p>1、 基于 Django 框架实现后台 Restful 风格的 API 开发</p>
<p>2、 利用<strong>FastDFS</strong>结合FastDHT实现用户上传文件的分布式去重存储</p>
<p>3、 使用<strong>Mysql</strong>存储数据，配置主从热备，水平分表</p>
<p>4、 利用websocket打造一套课程咨询系统，做到用户能和在线客服进行聊天沟通</p>
<p>5、 Nginx反向代理django 利用异步 io 特性提供高并发支持</p>
<h4 id="项目三："><a href="#项目三：" class="headerlink" title="项目三："></a><strong>项目三：</strong></h4><p>​     盛世收藏          北京盛藏艺步品有限公司</p>
<h5 id="项目描述：-2"><a href="#项目描述：-2" class="headerlink" title="项目描述："></a><strong>项目描述：</strong></h5><p>​       一款专为收藏爱好者设计的一站式交易平台，为用户打造一个鉴定估价、藏品交易、线上线下拍卖、学习交流的艺术收藏专业性平台，为广大古玩、文玩珍宝、艺术品玩家和从业者搭建优质的生态系统。</p>
<p><strong>项目职责：</strong></p>
<p>1、基于 Tornado 框架实现后台 Restful 风格的 API 开发 </p>
<p>2、使用 Mysql 存储数据，配置主从热备，使用 Celery 实现异步邮箱和短信推送。 </p>
<p>3、利用 Websocket 实现后端消息主动推送，改造前端传统轮询技术框架 </p>
<p>4、使用 Redis 作为缓存介质，利用其分布式锁和队列的特性开发并测试抢单秒杀功能</p>
<h3 id="个人博客："><a href="#个人博客：" class="headerlink" title="个人博客："></a><strong>个人博客：</strong></h3><p>​        <strong>技术博客：<a href="https://chenkai0309.gitee.io/blog/">https://chenkai0309.gitee.io/blog/</a></strong></p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/04/redis主从部署/">
                redis主从部署
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-04</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h2 id="redis-主从配置"><a href="#redis-主从配置" class="headerlink" title="redis 主从配置"></a><code>redis</code> 主从配置</h2><ul>
<li><h3 id="概念："><a href="#概念：" class="headerlink" title="概念："></a>概念：</h3><ul>
<li>一个主可以拥有多个从，如此形成多级服务器，共用一个<code>redis</code>实例</li>
<li>避免<code>redis</code>主服务挂掉，数据损失，服务破坏，设置从服务器为了备份数据，掠阵备用</li>
<li>也可以读写分离，主写数据，从读数据，提高读写效率  读写比例 10:1</li>
</ul>
</li>
</ul>
<h3 id="配置主"><a href="#配置主" class="headerlink" title="配置主"></a>配置主</h3><p>查看本地<code>ip</code></p>
<ul>
<li>命令： <code>ipconfig</code></li>
<li>然后打开指定文件绑定本地<code>IP</code><ul>
<li><code>sudo vi /etc/redis/redis.conf</code></li>
<li>找到 <code>bind 127.0.0.1</code>注释掉</li>
<li>添加一行 <code>bind 查到机器的本地IP</code></li>
<li>保存退出</li>
</ul>
</li>
</ul>
<h4 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h4><ul>
<li>命令：<ul>
<li><code>sudo service redis stop</code></li>
<li><code>redis-server redis.conf</code></li>
</ul>
</li>
<li>这里执行<code>sudo redis-server /etc/redis/redis.conf</code></li>
<li><code>cd /etc/redis/</code></li>
<li>拷贝一份备用<ul>
<li><code>sudo cp redis.conf slaveof.conf</code></li>
</ul>
</li>
<li><code>sudo vi slaveof.conf</code></li>
<li>修改<ul>
<li><code>port 改为6378</code> # 做个区别</li>
<li>在最后一行加入<ul>
<li><code>slaveof 主IP  6379</code>   #主从复制，类似于双机备份 主从备份</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="配置从"><a href="#配置从" class="headerlink" title="配置从"></a>配置从</h3><ul>
<li><code>sudo redis-server /etc/redis/slaveof.conf</code></li>
<li><code>redis-cli -h 主IP -p 6379 info Replication</code>   # 查看主关系  -p 6379 可以不写 默认6379<ul>
<li>连接主服务<ul>
<li><code>redis-cli -h 主IP</code></li>
</ul>
</li>
</ul>
</li>
<li><code>redis-cli -h ipconfig的IP -p 6378 info Replication</code>   # 查看从关系<ul>
<li><code>redis-cli -h ipconfig的IP -p 6378</code></li>
</ul>
</li>
</ul>
<p>ok 就这么简单！redis 主从 部署完成！</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/02/CentOs卸载mysql/">
                CentOs卸载mysql
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-02</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>当你遇到需要卸载CentOs卸载mysql时：</p>
<p>本人mysql 装的5.7，liunux版本百度云的centos 6.5</p>
<p>1.查看mysql的安装情况</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -qa|grep -i mysql</span><br></pre></td></tr></table></figure>

<p>2.停止mysql服务，删除mysql</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -ev mysql<span class="number">-5.1</span><span class="number">.73</span><span class="number">-8.</span>el6_8.x86_64</span><br></pre></td></tr></table></figure>

<p>注：       rpm -ev 上条命令查到的结果</p>
<p>注意：可能会抛依赖错误错 error:Failed dependencies:</p>
<p>，则在 尾部加上 –nodeps 不检查依赖关系删除，命令如下</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">rpm -e --nodeps mysql-libs<span class="number">-5.1</span><span class="number">.73</span><span class="number">-8.</span>el6_8.x86_64  </span><br><span class="line"></span><br><span class="line">或 rpm -e mysql-libs<span class="number">-5.1</span><span class="number">.73</span><span class="number">-8.</span>el6_8.x86_64 --nodeps  <span class="comment"># 都行</span></span><br></pre></td></tr></table></figure>

<p>3.删除遗留的mysql文件和依赖库</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">find / -name mysql</span><br><span class="line"></span><br><span class="line">rm -rf /var/lib/mysql</span><br></pre></td></tr></table></figure>

<p>4.mysql 配置文件还要手动删除</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -rf /etc/my.cnf</span><br></pre></td></tr></table></figure>



<p>5.检查一遍mysql 是否成功删除</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -qa|grep -i mysql</span><br></pre></td></tr></table></figure>

<p> ok  这样没什么问题的话  mysql就成功卸载掉了, 然后去安装你所需要的版本 ！！！</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/01/Django的Session存储Redis环境配置/">
                Django的Session存储Redis环境配置
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-01</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="Django的Session存储Redis环境配置"><a href="#Django的Session存储Redis环境配置" class="headerlink" title="Django的Session存储Redis环境配置"></a>Django的Session存储Redis环境配置</h1><p>第一步:在项目目录下的settings.py中MIDDLEWARE中加上中间件：<br># session中间件Django项目默认启用Session<br>‘django.contrib.sessions.middleware.SessionMiddleware’,</p>
<p>第二步：在redis中保存session，需要引入第三方扩展，我们可以使用django-redis来解决。<br>安装扩展<br>pip install django-redis</p>
<p>第三步：在settings.py文件中做如下设置<br># redis缓存配置<br>CACHES = {<br>“default”: {<br>“BACKEND”: “django_redis.cache.RedisCache”,<br>“LOCATION”: “redis://127.0.0.1:6379/1”, # 指明使用redis的1号数据库<br>“OPTIONS”: {<br>“CLIENT_CLASS”: “django_redis.client.DefaultClient”,<br>}<br>},<br>“session”: {<br>“BACKEND”: “django_redis.cache.RedisCache”,<br>“LOCATION”: “redis://127.0.0.1:6379/2”, # 指明使用redis的1号数据库<br>“OPTIONS”: {<br>“CLIENT_CLASS”: “django_redis.client.DefaultClient”,<br>}<br>}<br>}<br># session使用的存储方式<br>SESSION_ENGINE = “django.contrib.sessions.backends.cache”<br># 指明使用哪一个库保存session数据<br>SESSION_CACHE_ALIAS = “session”</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/08/29/对生产者-消费者的理解/">
                对生产者/消费者的理解
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-08-29</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>生产者消费者模式并不是GOF提出的23种设计模式之一，23种设计模式都是建立在面向对象的基础之上的，但其实面向过程的编程中也有很多高效的编程模式，生产者消费者模式便是其中之一，它是我们编程过程中最常用的一种设计模式。</p>
<p>在实际的软件开发过程中，经常会碰到如下场景：某个模块负责产生数据，这些数据由另一个模块来负责处理（此处的模块是广义的，可以是类、函数、线程、进程等）。产生数据的模块，就形象地称为生产者；而处理数据的模块，就称为消费者。</p>
<p> 单单抽象出生产者和消费者，还够不上是生产者／消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间，作为一个中介。生产者把数据放入缓冲区，而消费者从缓冲区取出数据。大概的结构如下图。</p>
<p><img src="https://img-blog.csdn.net/20161101155643986?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="img"></p>
<p> 1、你把信写好——相当于生产者制造数据</p>
<p> 2、你把信放入邮筒——相当于生产者把数据放入缓冲区</p>
<p> 3、邮递员把信从邮筒取出——相当于消费者把数据取出缓冲区</p>
<p> 4、邮递员把信拿去邮局做相应的处理——相当于消费者处理数据</p>
<p>### </p>
<h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><p>可能有同学会问了：这个缓冲区有什么用捏？为什么不让生产者直接调用消费者的某个函数，直接把数据传递过去？搞出这么一个缓冲区作甚？</p>
<p> 其实这里面是大有讲究的，大概有如下一些好处。</p>
<h4 id="◇解耦"><a href="#◇解耦" class="headerlink" title="◇解耦"></a>◇解耦</h4><p> 假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法，那么生产者对于消费者就会产生依赖（也就是耦合）。将来如果消费者的代码发生变化，可能会影响到生产者。而如果两者都依赖于某个缓冲区，两者之间不直接依赖，耦合也就相应降低了。</p>
<p> 接着上述的例子，如果不使用邮筒（也就是缓冲区），你必须得把信直接交给邮递员。有同学会说，直接给邮递员不是挺简单的嘛？其实不简单，你必须得认识谁是邮递员，才能把信给他（光凭身上穿的制服，万一有人假冒，就惨了）。这就产生和你和邮递员之间的依赖（相当于生产者和消费者的强耦合）。万一哪天邮递员换人了，你还要重新认识一下（相当于消费者变化导致修改生产者代码）。而邮筒相对来说比较固定，你依赖它的成本就比较低（相当于和缓冲区之间的弱耦合）。</p>
<h4 id="◇支持并发（concurrency）"><a href="#◇支持并发（concurrency）" class="headerlink" title="◇支持并发（concurrency）"></a>◇支持并发（concurrency）</h4><p> 生产者直接调用消费者的某个方法，还有另一个弊端。由于函数调用是同步的（或者叫阻塞的），在消费者的方法没有返回之前，生产者只好一直等在那边。万一消费者处理数据很慢，生产者就会白白糟蹋大好时光。</p>
<p> 使用了生产者／消费者模式之后，生产者和消费者可以是两个独立的并发主体（常见并发类型有进程和线程两种，后面的帖子会讲两种并发类型下的应用）。生产者把制造出来的数据往缓冲区一丢，就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。</p>
<p> 其实当初这个模式，主要就是用来处理并发问题的。</p>
<p> 从寄信的例子来看。如果没有邮筒，你得拿着信傻站在路口等邮递员过来收（相当于生产者阻塞）；又或者邮递员得挨家挨户问，谁要寄信（相当于消费者轮询）。不管是哪种方法，都挺土的。</p>
<h4 id="◇支持忙闲不均"><a href="#◇支持忙闲不均" class="headerlink" title="◇支持忙闲不均"></a>◇支持忙闲不均</h4><p> 缓冲区还有另一个好处。如果制造数据的速度时快时慢，缓冲区的好处就体现出来了。当数据制造快的时候，消费者来不及处理，未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来，消费者再慢慢处理掉。</p>
<p> 为了充分复用，我们再拿寄信的例子来说事。假设邮递员一次只能带走1000封信。万一某次碰上情人节（也可能是圣诞节）送贺卡，需要寄出去的信超过1000封，这时候邮筒这个缓冲区就派上用场了。邮递员把来不及带走的信暂存在邮筒中，等下次过来时再拿走。</p>
<p> 费了这么多口水，希望原先不太了解生产者／消费者模式的同学能够明白它是怎么一回事。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/08/24/redis 安装开机自启动方法/">
                redis 安装开机自启动方法
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-08-24</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>一、首先是下载Redis（这里我选择64位） github下载地址：<a href="https://github.com/MicrosoftArchive/redis/releases" target="_blank" rel="noopener">https://github.com/MicrosoftArchive/redis/releases</a>    </p>
<p>二、解压压缩包，进入安装目录 在空白处按下shift+鼠标右键，打开命令窗口。   </p>
<p>三、输入命令执行：redis-server –service-install redis.windows.conf   </p>
<p>四、设置开机自动启动 打开cmd窗口并输入：services.msc   找到Redis点击启动即可。 </p>
<p>五、（附）设置Redis的密码 进入Redis的安装目录打开：redis.windows-conf，按下Ctrl+F查找：requirepass，找到编辑保存然后重新启动Redis服务即可。（注意：这里是redis.windows-conf，windows自启动会加载这个配置文件）。   密码建议设置得复杂一点 </p>
<p>六、（附）绑定Redis的IP 按下Ctrl+F查找：127.0.0.1，找到编辑保存然后重新启动Redis服务即可。   </p>
<p>七、测试修改是否成功。 进入Redis安装目录，点击运行：redis-cli.exe，并输入用户名和密码。 </p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/08/01/高性能异步爬虫/">
                高性能异步爬虫
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-08-01</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="线程池-适当使用"><a href="#线程池-适当使用" class="headerlink" title="线程池(适当使用)"></a>线程池(适当使用)</h1><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">import re</span><br><span class="line">import requests</span><br><span class="line">from lxml import etree</span><br><span class="line">from multiprocessing.dummy import Pool</span><br><span class="line">import random</span><br><span class="line">headers = &#123;</span><br><span class="line">    &apos;User-Agent&apos;:&apos;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36&apos;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">def request_video(url):</span><br><span class="line">    return requests.get(url=url,headers=headers).content</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def saveVideo(data):</span><br><span class="line">    name = str(random.randint(0,9999))+&apos;.mp4&apos;</span><br><span class="line">    with open(name,&apos;wb&apos;) as fp:</span><br><span class="line">        fp.write(data)</span><br><span class="line">        print(name,&apos;下载存储成功！！！&apos;)</span><br><span class="line"></span><br><span class="line">url = &apos;https://www.pearvideo.com/category_1&apos;</span><br><span class="line">page_text = requests.get(url=url,headers=headers).text</span><br><span class="line"></span><br><span class="line">tree = etree.HTML(page_text)</span><br><span class="line">li_list = tree.xpath(&apos;//ul[@id=&quot;listvideoListUl&quot;]/li&apos;)</span><br><span class="line">#实例化一个线程池对象</span><br><span class="line">pool = Pool(4)</span><br><span class="line">video_url_list = [] #所有的视频连接</span><br><span class="line">for li in li_list:</span><br><span class="line">    detail_url = &apos;https://www.pearvideo.com/&apos;+li.xpath(&apos;./div/a/@href&apos;)[0]</span><br><span class="line">    detail_page_text = requests.get(url=detail_url,headers=headers).text</span><br><span class="line">    ex = &apos;srcUrl=&quot;(.*?)&quot;,vdoUrl=&apos;</span><br><span class="line">    video_url = re.findall(ex,detail_page_text,re.S)[0]</span><br><span class="line">    video_url_list.append(video_url)</span><br><span class="line">#异步的获取4个视频的二进制数据</span><br><span class="line">video_data_list = pool.map(request_video,video_url_list)</span><br><span class="line"></span><br><span class="line">#进行视频的持久化存储</span><br><span class="line">pool.map(saveVideo,video_data_list)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p><a href="https://www.cnblogs.com/wanglan/p/10821140.html#_labelTop" target="_blank" rel="noopener">回到目录</a></p>
<h1 id="单线程-异步协程-推荐"><a href="#单线程-异步协程-推荐" class="headerlink" title="单线程+异步协程(推荐)"></a>单线程+异步协程(推荐)</h1><ul>
<li>event_loop：事件循环，相当于一个无限循环，我们可以把一些函数注册到这个事件循环上，当满足某些条件的时候，函数就会被循环执行。程序是按照设定的顺序从头执行到尾，运行的次数也是完全按照设定。当在编写异步程序时，必然其中有部分程序的运行耗时是比较久的，需要先让出当前程序的控制权，让其在背后运行，让另一部分的程序先运行起来。当背后运行的程序完成后，也需要及时通知主程序已经完成任务可以进行下一步操作，但这个过程所需的时间是不确定的，需要主程序不断的监听状态，一旦收到了任务完成的消息，就开始进行下一步。loop就是这个持续不断的监视器。</li>
<li>coroutine：中文翻译叫协程，在 Python 中常指代为协程对象类型，我们可以将协程对象注册到事件循环中，它会被事件循环调用。我们可以使用 async 关键字来定义一个方法，这个方法在调用时不会立即被执行，而是返回一个协程对象。</li>
<li>task：任务，它是对协程对象的进一步封装，包含了任务的各个状态。</li>
<li>future：代表将来执行或还没有执行的任务，实际上和 task 没有本质区别。</li>
<li>另外我们还需要了解 async/await 关键字，它是从 Python 3.5 才出现的，专门用于定义协程。其中，async 定义一个协程，await 用来挂起阻塞方法的执行。</li>
</ul>
<h3 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h3><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">#基本使用</span><br><span class="line">import asyncio</span><br><span class="line">async def hello(name):</span><br><span class="line">    print(&apos;hello to :&apos;,name)</span><br><span class="line">#获取了一个协程对象</span><br><span class="line">c = hello(&apos;bobo&apos;)</span><br><span class="line"></span><br><span class="line">#创建一个事件循环对象</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line"></span><br><span class="line">#将协程对象注册到事件循环中，然后启动事件循环对象</span><br><span class="line">loop.run_until_complete(c)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h3 id="task的使用"><a href="#task的使用" class="headerlink" title="task的使用"></a>task的使用</h3><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">#task的使用</span><br><span class="line">import asyncio</span><br><span class="line">async def hello(name):</span><br><span class="line">    print(&apos;hello to :&apos;,name)</span><br><span class="line"></span><br><span class="line">#获取了一个协程对象</span><br><span class="line">c = hello(&apos;bobo&apos;)</span><br><span class="line">#创建一个事件循环对象</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line">#就协程进行进一步的封装，封装到了task对象中</span><br><span class="line">task = loop.create_task(c)</span><br><span class="line">print(task)</span><br><span class="line">loop.run_until_complete(task)</span><br><span class="line">print(task)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h3 id="future"><a href="#future" class="headerlink" title="future"></a>future</h3><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#future</span><br><span class="line">import asyncio</span><br><span class="line">async def hello(name):</span><br><span class="line">    print(&apos;hello to :&apos;,name)</span><br><span class="line"></span><br><span class="line">c = hello(&apos;bobo&apos;)</span><br><span class="line">task = asyncio.ensure_future(c)</span><br><span class="line">loop.run_until_complete(task)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h3 id="绑定回调-task"><a href="#绑定回调-task" class="headerlink" title="绑定回调(task)"></a>绑定回调(task)</h3><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">import asyncio</span><br><span class="line">def callback(task):</span><br><span class="line">    print(&apos;i am callback:&apos;,task.result())</span><br><span class="line"></span><br><span class="line">async def hello(name):</span><br><span class="line">    print(&apos;hello to :&apos;,name)</span><br><span class="line">    return name</span><br><span class="line"></span><br><span class="line">c = hello(&apos;bobo&apos;)</span><br><span class="line"></span><br><span class="line">task = asyncio.ensure_future(c)</span><br><span class="line">#给任务对象绑定一个回调函数</span><br><span class="line">task.add_done_callback(callback)</span><br><span class="line">loop.run_until_complete(task)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h3 id="多任务异步协程"><a href="#多任务异步协程" class="headerlink" title="多任务异步协程"></a>多任务异步协程</h3><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">import requests</span><br><span class="line">async def get_page(url):</span><br><span class="line">    print(&apos;正在下载：&apos;,url)</span><br><span class="line">    #之所以没有实现异步操作，原因是因为requests模块是一个非异步的模块</span><br><span class="line">    response = requests.get(url=url)</span><br><span class="line">    print(&apos;响应数据：&apos;,response.text)</span><br><span class="line">    print(&apos;下载成功：&apos;,url)</span><br><span class="line">start = time.time()</span><br><span class="line">urls = [</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;</span><br><span class="line">]</span><br><span class="line">tasks = []</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line">for url in urls:</span><br><span class="line">    c = get_page(url)</span><br><span class="line">    task = asyncio.ensure_future(c)</span><br><span class="line">    tasks.append(task)</span><br><span class="line">loop.run_until_complete(asyncio.wait(tasks))</span><br><span class="line">print(&apos;总耗时：&apos;,time.time()-start)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<p>asyncio.sleep()</p>
<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">import asyncio</span><br><span class="line">async def request(url):</span><br><span class="line">    print(&apos;正在下载：&apos;,url)</span><br><span class="line">#     sleep(2) #非异步模块的代码：在此处如果存在非异步操作代码，则会彻底让asyncio失去异步的效果</span><br><span class="line">    await asyncio.sleep(2)</span><br><span class="line">    print(&apos;下载成功：&apos;,url)</span><br><span class="line">urls = [</span><br><span class="line">    &apos;www.baidu.com&apos;,</span><br><span class="line">    &apos;www.taobao.com&apos;,</span><br><span class="line">    &apos;www.sogou.com&apos;</span><br><span class="line">]</span><br><span class="line">start = time.time()</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line">tasks = [] #任务列表，放置多个任务对象</span><br><span class="line">for url in urls:</span><br><span class="line">    c = request(url)</span><br><span class="line">    task = asyncio.ensure_future(c)</span><br><span class="line">    tasks.append(task)</span><br><span class="line">    </span><br><span class="line">#将多个任务对象对应的列表注册到事件循环中</span><br><span class="line">loop.run_until_complete(asyncio.wait(tasks))</span><br><span class="line">print(&apos;总耗时：&apos;,time.time()-start)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h3 id="多任务异步操作应用到爬虫中"><a href="#多任务异步操作应用到爬虫中" class="headerlink" title="多任务异步操作应用到爬虫中"></a>多任务异步操作应用到爬虫中</h3><ul>
<li>环境安装：pip install aiohttp  支持异步的网络请求的模块</li>
</ul>
<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">import aiohttp</span><br><span class="line">import asyncio</span><br><span class="line"></span><br><span class="line">async def get_page(url):</span><br><span class="line">    async with aiohttp.ClientSession() as session:</span><br><span class="line">        async with await session.get(url=url) as response:</span><br><span class="line">            page_text = await response.text() #read()  json()</span><br><span class="line">            print(page_text)</span><br><span class="line">start = time.time()</span><br><span class="line">urls = [</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;</span><br><span class="line">]</span><br><span class="line">tasks = []</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line">for url in urls:</span><br><span class="line">    c = get_page(url)</span><br><span class="line">    task = asyncio.ensure_future(c)</span><br><span class="line">    tasks.append(task)</span><br><span class="line">loop.run_until_complete(asyncio.wait(tasks))</span><br><span class="line">print(&apos;总耗时：&apos;,time.time()-start)</span><br></pre></td></tr></table></figure>

<p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<h3 id="实现数据解析—任务的绑定回调机制"><a href="#实现数据解析—任务的绑定回调机制" class="headerlink" title="实现数据解析—任务的绑定回调机制"></a>实现数据解析—任务的绑定回调机制</h3><p><a href="javascript:void(0);" target="_blank" rel="noopener"><img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">import aiohttp</span><br><span class="line">import asyncio</span><br><span class="line">#回调函数：解析响应数据</span><br><span class="line">def callback(task):</span><br><span class="line">    print(&apos;this is callback()&apos;)</span><br><span class="line">    #获取响应数据</span><br><span class="line">    page_text = task.result()</span><br><span class="line">    print(&apos;在回调函数中，实现数据解析&apos;)</span><br><span class="line">    </span><br><span class="line">async def get_page(url):</span><br><span class="line">    async with aiohttp.ClientSession() as session:</span><br><span class="line">        async with await session.get(url=url) as response:</span><br><span class="line">            page_text = await response.text() #read()  json()</span><br><span class="line">#             print(page_text)</span><br><span class="line">            return page_text</span><br><span class="line">start = time.time()</span><br><span class="line">urls = [</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/bobo&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/jay&apos;,</span><br><span class="line">    &apos;http://127.0.0.1:5000/tom&apos;</span><br><span class="line">]</span><br><span class="line">tasks = []</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line">for url in urls:</span><br><span class="line">    c = get_page(url)</span><br><span class="line">    task = asyncio.ensure_future(c)</span><br><span class="line">    #给任务对象绑定回调函数用于解析响应数据</span><br><span class="line">    task.add_done_callback(callback)</span><br><span class="line">    tasks.append(task)</span><br><span class="line">loop.run_until_complete(asyncio.wait(tasks))</span><br><span class="line">print(&apos;总耗时：&apos;,time.time()-start)</span><br></pre></td></tr></table></figure>
        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/07/18/关于jQuery/">
                关于jQuery
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-07-18</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>#jQuery</p>
<p>jQuery是一个JavaScript函数库。</p>
<p>jQuery是一个轻量级的JavaScript库。</p>
<p>jQuery库包含以下功能：</p>
<ul>
<li>HTML 元素选取</li>
<li>HTML 元素操作</li>
<li>CSS 操作</li>
<li>HTML 事件函数</li>
<li>JavaScript 特效和动画</li>
<li>HTML DOM 遍历和修改</li>
<li>AJAX 异步加载<br>jQuery介绍<br>jQuery是目前使用最广泛的javascript函数库。据统计，全世界排名前100万的网站，有46%使用jQuery，远远超过其他库</li>
</ul>
<p>微软公司甚至把jQuery作为他们的官方库</p>
<p>jQuery的版本分为1.x系列和2.x、3.x系列，1.x系列兼容低版本的浏览器；2.x、3.x系列放弃支持低版本浏览器，目前使用最多的是1.x系列的</p>
<p>jquery是一个函数库，一个js文件，页面用script标签引入这个js文件就可以使用</p>
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<p>下载jQuery<br>官网：<a href="http://jquery.com/" target="_blank" rel="noopener">http://jquery.com/</a><br>下载：<a href="https://code.jquery.com/" target="_blank" rel="noopener">https://code.jquery.com/</a><br>基础语法</p>
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
    $(document).ready( function(){
        $("p").click( function(){
            console.log($(this).css("color"))
            $(this).css("color","red");
        });
    })
</script>
<body>
    <p style="color: blue;">我会变红</p>
</body>
Jquery基础语法：Query 语法是通过选取 HTML 元素，并对选取的元素执行某些操作
$(selector).action()
美元符号定义jQuery

<p>选择符（selector）查询和查找HTML元素</p>
<p>jQuery的action()执行对元素的操作</p>
<p>文档就绪事件<br>这是为了防止文档在完全加载（就绪）之前运行jQuery代码，jQuery的代码经常会位于一个document ready函数中<br>$(document).ready(function(){</p>
<p>   // 开始写 jQuery 代码…</p>
<p>});<br>注意<br>jQuery入口函数与JavaScript入口函数的区别</p>
<p>jQuery的入口函数是在html所有标签(DOM)都加载之后，就会去执行</p>
<p>JavaScript的window.onload事件是等到所有内容，包括外部图片之类的文件加载完后，才会执行</p>
<p>jQuery选择器<br>jQuery的选择器可以更加方便我们对页面的DOM元素进行操作，而原生的操作方式是比较痛苦的</p>
<p>元素选择器<br>jQuery选择器允许对HTML元素组或单个元素进行操作</p>
<head><meta name="generator" content="Hexo 3.9.0">
    <title></title>
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>

<pre><code>&lt;script type=&quot;text/javascript&quot;&gt;
    $(document).ready(function(){
        $(&quot;p&quot;).click(function(){
            $(this).css(&quot;color&quot;,&quot;red&quot;);
        });
    });
&lt;/script&gt;
&lt;!-- 当某个p被点击时，都会触发该js函数 --&gt;</code></pre></head>
<body>
    <p>我是第一个p</p>
    <p>我是第二个p</p>
    <p>我是第三个p</p>
</body>
ID选择器
ID选择器通过HTML元素的ID属性选取指定的元素

<p>页面中的元素的id应该是唯一的，在页面中选取唯一的元素需要#id选择器</p>
<head><meta name="generator" content="Hexo 3.9.0">
    <title></title>
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){
            $("#change").click(function(){
                $(this).css("color","red"); // css属性函数
            });
        });
    </script>
    <!-- 当Id值为change的p标签被点击时，触发该js函数 -->
</head>
<body>
    <p>我是第一个p</p>
    <p>我是第二个p</p>
    <p id="change">我是第三个p</p>
</body>
类选择器
通过元素的class属性进行查找
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("button").click(function(){
                $(".pClass").hide();
            });
        });    
    </script>
</head>
<body>
    <p class="pClass">
        这是测试内容，点击按钮后，这里的东西会消失
    </p>
    <button>
        点击
    </button>
</body>
其他选择器
语法    描述
$(this)    选取当前HTML元素
$("*")    选取所有元素
$("p.intro")    选取class为intro的<p>元素
$("p:first")    选取第一个</p><p> 元素
$("ul li:first")    选取第一个<ul>元素的第一个<li>元素
$("ul li:first-child")    选取每个<ul>元素的第一个<li>元素
$("[href]")    选取带有href属性的元素
$("a[target='_blank']")    选取所有target属性值等于_blank的<a>元素
$(":button")    选取所有type="button"的 <input>元素 和<button>元素
$("tr:odd")    选取奇数位置的<tr>元素
jQuery遍历
在查找时,可以通过遍历,相对于某些元素进行位置查找,从而获取到想要的元素位置

<p>先要分清楚在HTML中元素的级别关系</p>
<div>
    <ul>
        <li> <span>a</span> </li>
        <li> <a> b </a> </li>
    </ul>
</div>
- <div> 元素是 <ul> 的父元素，同时是其中所有内容的祖先。
- <ul> 元素是 <li> 元素的父元素，同时是 <div> 的子元素
- 左边的 <li> 元素是 <span> 的父元素，<ul> 的子元素，同时是 <div> 的后代。
- <span> 元素是 <li> 的子元素，同时是 <ul> 和 <div> 的后代。
- 两个 <li> 元素是同胞（拥有相同的父元素）。
- 右边的 </li><li> 元素是 <a> 的父元素，<ul> 的子元素，同时是 <div> 的后代。
- <a> 元素是右边的 <li> 的子元素，同时是 <ul> 和 <div> 的后代。
  祖先遍历
  parent()：返回被选择元素的直接父元素
  <head><meta name="generator" content="Hexo 3.9.0">
  <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>

<pre><code>&lt;script&gt;
    $(document).ready(function(){
        $(&quot;span&quot;).parent().css(&quot;border&quot;,&quot;1px solid red&quot;);
    });
&lt;/script&gt;
// 这里选择到了全部span标签的父标签,li标签,并且设置红色2像素边框</code></pre>  </head>

<body>
    <div>
        <ul>
            <li> 
                <span>普通内容1</span>
            </li>
            <br>
            <li> 
                <span>普通内容2</span>
                <br>
                <a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a> 
            </li>
        </ul>
    </div>
</body>
parents()：返回被选择元素的全部父元素
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("span").parents().css("border","1px solid red");
        });
        // 选中了li标签 ul标签 div标签
    </script>
</head>
<body>
    <div>
        <ul>
            <li> 
                <span>普通内容1</span>
            </li>
            <br>
            <li> 
                <a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a> 
            </li>
        </ul>
    </div>
</body>
该方法也可以指定父元素中的某些元素进行二次过滤，比如选择所有父元素中类为father的元素
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("span").parents(".father").css("border","1px solid red");
        });
        // 找到了 div标签和ul标签
    </script>
</head>
<body>
    <div class="father">
        <ul class="father">
            <li> 
                <span>普通内容1</span>
            </li>
            <br>
            <li> 
                <a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a> 
            </li>
        </ul>
    </div>
</body>
</html>
parentsUntil("limit")：向上查找,直到找到元素界限为止之前的所有父元素
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("span").parentsUntil("div").css("border","1px solid red");
        });
        // 找到了 ul标签 第一个li标签
    </script>
</head>
<body>
    <div class="father">
        <ul class="father">
            <li> 
                <span>普通内容1</span>
            </li>
            <br>
            <li> 
                <a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a> 
            </li>
        </ul>
    </div>
</body>
</html>
后代遍历
children()：返回被选元素的直接子元素，不会继续向深层次遍历
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("li").children().css("border","1px solid red");
        });
        // 找到了 span标签 a标签
    </script>
</head>
<body>
    <div class="father">
        <ul class="father">
            <li> 
                <span>普通内容1</span>
            </li>
            <br>
            <li> 
                <a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a> 
            </li>
        </ul>
    </div>
</body>
</html>
find("*")：返回被选元素的所有符合条件的直接子元素，会继续向深层次遍历
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("ul").find("*").css("border","1px solid red");
        });
        // 找到了 两个li标签 span标签 a标签
    </script>
</head>
<body>
    <div class="father">
        <ul class="father">
            <li> 
                <span>普通内容1</span>
            </li>
            <br>
            <li> 
                <a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a> 
            </li>
        </ul>
    </div>
</body>
</html>
同胞遍历
siblings()：返回被选元素的所有同胞元素
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("span").siblings().css("border","1px solid red");
        });
        // 找到了 p标签 h标签 strong标签
    </script>
</head>
<body>
    <div class="father">
        <p>一个p标签</p>
        <span>一个span标签</span>
        <h3>一个h标签</h3>
        <strong>一个strong标签</strong>
    </div>
</body>
</html>
next()：返回被选元素的下一个同胞元素，只返回一个元素

<p>nextAll()：返回被选元素的所有下面的同胞元素，返回所有跟随同胞</p>
<p>nextUntil(“limit”)：返回直到limit界限的所有跟随同胞，不包含limit</p>
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("span").next().css("border","1px solid red");
        });
        // 找到了 h标签
    </script>
</head>
<body>
    <div class="father">
        <p>一个p标签</p>
        <span>一个span标签</span>
        <h3>一个h标签</h3>
        <strong>一个strong标签</strong>
    </div>
</body>
</html>
过滤方法
语法    描述
first()    返回被选元素的首个元素
last()    返回被选元素的最后个元素
eq()    返回被选元素中带有指定索引号的元素，索引从0开始
filter()    规定一个标准。不匹配这个标准的元素会被从集合中删除，匹配的元素会被返回
not()    返回不匹配标准的所有元素，与filter相反
$("h3").filter(".suit");
// 选择所有类名为suit的h3标签
$("p").not(".green");
// 过滤所有类名为green的p标签
判断是否选择到了元素
jquery有容错机制，即使没有找到元素，也不会出错

<p>可以用length属性来判断是否找到了元素，length等于0，就是没选择到元素；length大于0，就是选择到了元素</p>
<p>var oh = $(“h1”);<br>alert(oh.length) // &gt; 1 | 0<br>jQuery样式操作<br>获取样式<br>$(“selector”).css(“attr”)<br>$(“div”).css(“color”); // rgb(255, 0, 0)<br>$(“div”).css(“border”); // 1px solid rgb(128, 128, 128)<br>设置样式<br>$(“selector”).css(“attr”,”xxx”)</p>
<p>$(“selector”).css({“attr1”: “xxx”, “attr2”: “yyy”})</p>
<p>$(“div”).css(“color”,”blue”);<br>$(“div”).css({“color”:”blue”, “border”:”1px dashed yellow”});<br>注意:如果选择器div选择到了多个,在获取信息时,只取第一个<br>其他操作样式的方式<br>addClass()：向被选元素添加一个或多个属性</p>
<style type="text/css">
.redFont{
    color: red;
}
.blueBoder{
    border: 1px solid blue;
}
</style>
<p>$(document).ready(function(){<br>    $(“button”).click(function(){<br>        $(“.father”).addClass(“redFont blueBoder”);<br>    });<br>});</p>
<div class="father">
    这是个div
</div>
<button>按钮</button>
removeClass()：删除指定的class属性
<style type="text/css">
    .redFont{
        color: red;
    }
    .blueBoder{
        border: 1px solid blue;
    }
</style>
$(document).ready(function(){
    $("button").click(function(){
        $(".redFont").removeClass("blueBoder");
    });
});
<div class="blueBoder redFont">
    这是个div
</div>
<button>按钮</button>
toggleClass()：设置或移除被选元素的一个或多个类进行切换
该方法检查每个元素中指定的类

<p>如果不存在则添加类，如果已设置则删除之。这就是所谓的切换效果</p>
<div class="blueBoder redFont">
    这是个div
</div>
<button>按钮</button>
$(document).ready(function(){
    $("button").click(function(){
        $("p").toggleClass("redFont");
    });
});
<p class="redFont">第一段文字</p>
<p class="redFont">第二段文字</p>
<p>第三段文字</p>
<p>第四段文字</p>
<h3>这是h3标题</h3>
<button>按钮</button>
jQuery事件
鼠标事件
click：点击
$(selector).click(function(){
    ...    
});
dbclick：双击
$(selector).dbclick(function(){
    ...    
});
mouseenter：穿过某元素
$(selector).mouseenter(function(){
    ...    
});
moseleave：鼠标离开
$(selector).mouseleave(function(){
   ... 
});
hover：鼠标悬停
$(selector).hover(function(){
    ...
});
键盘事件
keydown：键按下的过程
$(selector).keydown(function(){
    //
});
keypress：键被按下
i = 0
$(document).ready(function(){
    $("input").keypress(function(){
        $("span").text(i+=1);
    });
});
// 在input表单中按了多少次
<input type="text">
<p>按键的次数: <span>0</span></p>
keyup：键被松开
$(selector).keyup(function(){
   // 
});
表单事件
submit：表单提交
$("form").submit(function(){
   alert("表单被提交");
});
change：表单修改
$("input").change(function(){
    alert("文本已被修改");
});
注意：当用于select元素时，change事件会在选择某个选项时发生。当用于text field或text area 时，change事件会在元素失去焦点时发生

<p>focus：光标选中</p>
<p>$(“input”).focus(function(){<br>    $(“label”).fadeOut(2000);<br>});<br>// 当输入框被选中时，label标签淡出 fadeOut<br><label>看看这个文字</label><br><input type="text"><br>blur：光标离开<br>$(“input”).blur(function(){<br>    alert(“输入框失去了焦点”);<br>});<br>文档/窗口事件<br>load：指定元素已加载<br>load()方法在jQuery版本1.8中已废弃</p>
<p>$(“img”).load(function(){<br>    alert(“图片已载入”);<br>});<br>resize：当调整浏览器窗口大小时，发生resize事件<br>$(window).resize(function(){<br>   $(“span”).text(i+=1);<br>});<br><span>0</span>次<br>scroll：当用户滚动指定的元素时，会发生scroll事件<br>scroll事件适用于所有可滚动的元素和window对象（浏览器窗口）</p>
<p>$(“div”).scroll(function(){<br>    $(“span”).text(x+=1);<br>});<br>unload：当用户离开页面时，会发生unload事件<br>unload()方法在jQuery版本1.8中已废弃，在3.0版本被移除</p>
<p>$(window).unload(function(){<br>    alert(“Goodbye!”);<br>});<br>// unload() 方法只应用于 window 对象<br>获取内容和属性<br>text()：设置或返回所选元素的文本内容<br>html()：设置或返回所选元素的内容（包括HTML标记）</p>
<p>这是个<b>p</b>标签</p>
 <button>按钮</button>
$("button").click(function(){
    console.log($("p").text()); // 这是个p标签
    console.log($("p").html()); // 这是个<b>p</b>标签
});
val()：设置或返回表单字段的值
<input type="text" value="123">
<button>按钮</button>
$("button").click(function(){
    console.log($("input").val());
});
attr("src")：获取属性
<a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a>
<button>按钮</button>
$("button").click(function(){
        console.log($("a").attr("href")); // https://www.baidu.com
});
// 获取a标签的href属性
改变内容和属性
text()、html()、val()
$("button").click(function(){
    $("#test1").text("Hello world!");
});
$("button").click(function(){
    $("#test2").html("<b>Hello world!</b>");
});
$("button").click(function(){
    $("#test3").val("RUNOOB");
});
attr()
以下是一个点击按钮将a标签的跳转地址变为搜狗的示例

<p><a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a><br><button>按钮</button><br>$(document).ready(function(){<br>    $(“button”).click(function(){<br>      $(“a”).attr(“href”,”<a href="https://www.sougou.com&quot;" target="_blank" rel="noopener">https://www.sougou.com&quot;</a>);<br>    });<br>});<br>// 同时设置多个属性</p>
<p>$(document).ready(function(){<br>    $(“a”).attr({<br>        “href” : “<a href="https://www.sougou.com&quot;" target="_blank" rel="noopener">https://www.sougou.com&quot;</a>,<br>        “class” : “sougou”<br>    });<br>});<br>jQuery效果<br>显示|隐藏<br>hide(speed:[slow|fast], callback)：隐藏元素<br>show(speed:[slow|fast], callback)：显示元素</p>
<p>这是一段文字</p>
<button id="hide">hide</button> 
<button id="show">show</button>
$(document).ready(function(){
    $("#hide").click(function(){
        $("p").hide("slow");
    });

<pre><code>$(&quot;#show&quot;).click(function(){
    $(&quot;p&quot;).show();
});</code></pre><p>});<br>toggle()：显示被隐藏的元素，并隐藏已显示的元素</p>
<p>这是一段文字</p>
<button>按钮</button>
$("button").click(function(){
  $("p").toggle();
});
淡入|淡出
fadeIn()：淡入已隐藏的元素
<p id="p1">这是一段文字</p>
<p id="p2">这是一段文字</p>
<p id="p3">这是一段文字</p>
<button>按钮</button>
$(document).ready(function(){
    $("p").hide() // 隐藏元素
    $("button").click(function(){
        $("#p1").fadeIn();
        $("#p2").fadeIn("slow");
        $("#p3").fadeIn(3000);
    });
});
fadeOut()：淡出可见元素
<p id="p1">这是一段文字</p>
<p id="p2">这是一段文字</p>
<p id="p3">这是一段文字</p>
<button>按钮</button>
$(document).ready(function(){
    $("button").click(function(){
        $("#p1").fadeOut();
        $("#p2").fadeOut("slow");
        $("#p3").fadeOut(3000);
    });
});
fadeToggle()：在fadeIn()与fadeOut()方法之间进行切换
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("button").click(function(){
                $("#p1").fadeToggle();
                $("#p2").fadeToggle("slow");
                $("#p3").fadeToggle(3000);
            });
        });
    </script>
</head>

<body>
    <p id="p1">这是一段文字</p>
    <p id="p2">这是一段文字</p>
    <p id="p3">这是一段文字</p>
    <button>按钮</button> 
</body>
</html>
滑动
- slideDown(speed,callback) // 向下滑动元素
- slideUp(speed,callback) // 向上滑动元素
- slideToggle(speed,callback) // 在 slideDown() 与 slideUp() 方法之间进行切换
  // 可选的 speed 参数规定效果的时长。它可以取以下值："slow"、"fast" 或毫秒。
  // 可选的 callback 参数是滑动完成后所执行的函数名称
  jQuery动画
  $(selector).animate( {params}, speed, callback)

<p>params：可选参数；动画形成的属性，要改变的样式值，写成字典</p>
<p>speed：可选参数；动画持续的时间，单位毫秒<br>callback：可选参数；动画完成后执行的函数名称<br>注意：当使用animate()时，必须使用Camel标记法书写所有的属性名；比如，必须使用paddingLeft而不是padding-left，使用 marginRight 而不是margin-right，等等、同时，色彩动画并不包含在核心jQuery 库中</p>
<p style="position: relative;">这是一段文字</p>
<button>按钮</button>
$(document).ready(function(){
    $("button").click(function(){
        $("p").animate(
            {
                left: "+=300px",
                fontSize: "100px",
            },
            "slow",
            function(argument) {
                alert("动画完成")
            }
        )
    })
});
jQuery获取表单数据
单选框：radio
$("input[type=radio]:checked").val()
// 当一个页面有两个radio时
$("input[name='gender']:checked").val(); 
// 通过name分类进行过滤 checked代表选中元素
多选框：checkbox
var res = new Array;
var olike = $("input:checkbox[name='like']:checked").each(function(){
    res.push($(this).val())
})
// each() 方法规定为每个匹配元素规定运行的函数
下拉菜单：select
$("select[name='city']").val();
jQuery正则
正则规则
- \d：匹配一个数字
- \D：匹配一个非数字，即除了0-9
- \w：匹配字母、数字、下划线
- \W：匹配非单词字符，等价于\[^A-Za-z0-9_\]
- \s：匹配一个空白符
- \S：匹配一个非空白符
- \b：匹配单词边界
- \B：匹配非单词边界
- .：匹配任意字符
  开头结尾
- ^：开头匹配 
- $：结尾匹配
  正则次数
- ?：出现零次或一次；最多出现一次
- +：出现一次或多次；至少出现一次
- *：出现零次或多次；任意次
- {n,m}：出现n-m次
  匹配范围
- [a-z]：匹配任意小写字母
- [0-9]：匹配任意数字
  正则语法
  var regex = /规则/参数
  /\d+/ // 匹配所有数字
  创建正则表达式
  var regex = /[a-z]+$/ ; // 任意小写字母结尾
  var regex = new RegExp()
- g：全局的匹配(匹配多次；)
- i：大小写不敏感匹配(忽略字符大小写)
- m：多行(^和$能匹配行结束符)
  捕获型|非捕获型
  (?:(\d+)) // 非捕获型分组 结果并不会复制所匹配的文本
  (\d+) // 其中的\d+ 是捕获型分组，结果会放入最终的匹配结果中
  正则判断方法
  regex.exec：将匹配到的文本保存到一个结果数组
  本身的表达式是一个包含分组匹配的，那么使用exec可以将每个分组保存到数组结果的依次位置中
  regex.test：匹配成功返回true，否则返回假
  常用正则规则
  regAccount = /^\w{6,20}$/; // 字母数字下划线，用户名验证6-20位

<p>regEmail = /^[a-zA-z1-9]{8,20}@(163|126|qq).(com|cn)$/  // 邮箱验证</p>
<p>regPass = /^[\w!@#$%^&amp;*]{6,20}$/ // 密码验证</p>
<p>regPhone = /^1[3,4,5,7,8]\d{9}$/ // 手机号验证<br>sStr = “123456”<br>regex = /\d+/<br>alert(regex.test(sStr)); // true<br>AJAX<br>$.ajax([settings])：执行ajax请求<br>$(document).ready(function(){<br>    $(“button”).click(function(){<br>        $.ajax({<br>            url: “/ajax/“,// 发送请求的地址<br>            type: “POST”, // 请求方式 默认get<br>            data: { // 要提交的数据<br>                username:$(“#username”).val(),<br>                // “csrfmiddlewaretoken”:$(“[name=’csrfmiddlewaretoken’]”).val(), // django的csrf防跨站请求伪造令牌<br>            },</p>
<pre><code>        beforeSend: function(){ // 发送请求前运行的函数
            $(&quot;button&quot;).attr({ disabled: &quot;disabled&quot; })
        },

        success: function(result){ // 请求成功后的回调函数
            // 服务器返回根据datatype设定的类型数据
            $(&quot;#result&quot;).text(result)
            console.log(result)
        },
        complete: function(){ // 请求完成时运行的函数 
            // 在请求成功或失败之后均调用，即在 success 和 error 函数之后
            $(&quot;button&quot;).removeAttr(&quot;disabled&quot;);
        },
    })
});</code></pre><p>});<br>django服务端的功能：</p>
<h1 id="views-py"><a href="#views-py" class="headerlink" title="views.py"></a>views.py</h1><p>def ajax(request):<br>    if request.is_ajax(): # 判断是否是ajax请求<br>        print(request.POST)<br>        print(request.body)<br>        username = request.POST.get(“username”) #获取ajax传递来的数据中的 username对应的数据<br>        return  HttpResponse(json.dumps(“这是我获取到的:%s” % (username,)))<br>    response = render(request,”ajax.html”)<br>    return response</p>
</div></ul></li></a></div></ul></a></li></div></ul></li></span></div></ul></span></li></div></li></ul></ul></div></tr></button></a></li></ul></li></ul></p>
        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/07/06/djang0-Vue部署/">
                Djang0+Vue部署
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-07-06</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>说明：后文中出现的以下字符串均表示具体的路径或者名称，含义如下：</p>
<p>DJANGO_DIR—表示django的工程根目录 例如：/data/Datalable<br>DJANGO_NAME—表示django的工程名称 例如Datalable<br>VUE_HTML_DIR—表示vue的index.html路径 例如:/data/dist<br>VUE_STATIC_DIR—表示vue的static的路径 例如:/data/dist/static<br>修改配置文件nginx 打开 vim /etc/nginx/nginx.conf  在http中加入下面的配置文件</p>
<p>server {</p>
<pre><code>listen 8080;
server_name 132.232.50.225;
root /data/;
charset  utf-8;
access_log /data/access_narwhals.log;
error_log /data/error_narwhals.log;
client_max_body_size 75M;

location / {
        uwsgi_pass 127.0.0.1:9090;
        include /etc/nginx/uwsgi_params;
}

location ^~ /admin/ {
        uwsgi_pass 127.0.0.1:9090;
        include /etc/nginx/uwsgi_params;
}</code></pre><p>}</p>
<p>该配置中uwsgi_pass要指向uwsgi绑定的接口。（我们先假设uwsgi配置的是9090端口）</p>
<p>二、安装和配置uwsgi<br>安装<br>使用yum或者pip均可安装</p>
<p>yum install uwsgi</p>
<h1 id="或者"><a href="#或者" class="headerlink" title="或者"></a>或者</h1><p>pip install uwsgi</p>
<p>配置<br>uwsgi可以使用命令行启动，也可以使用配置文件来启动，推荐使用配置文件来启动守护进程，配置文件内容如下</p>
<p>[uwsgi]<br>socket = 127.0.0.1:9090</p>
<p>#<br>下面<br>IP<br>端口没弄明白做什么<br>stats = 127.0.0.1:9293<br>workers = 4</p>
<h1 id="项目根目录"><a href="#项目根目录" class="headerlink" title="项目根目录"></a>项目根目录</h1><p>chdir<br> = /test_service/DataLable<br>touch-reload = /test_service/DataLable<br>py-auto-reload = 1</p>
<h1 id="在项目跟目录和项目同名的文件夹里面的一个文件"><a href="#在项目跟目录和项目同名的文件夹里面的一个文件" class="headerlink" title="在项目跟目录和项目同名的文件夹里面的一个文件"></a>在项目跟目录和项目同名的文件夹里面的一个文件</h1><p>module= DataLable.wsgi<br>pidfile = /var/run/inner_manager.pid<br>daemonize = /data/uwsgi9090.log</p>
<h1 id="If-you-plan-to-receive-big-requests-with-lots-of-headers-you-can-increase-this-value-up-to-64k-65535"><a href="#If-you-plan-to-receive-big-requests-with-lots-of-headers-you-can-increase-this-value-up-to-64k-65535" class="headerlink" title="If you plan to receive big requests with lots of headers you can increase this value up to 64k (65535)."></a>If you plan to receive big requests with lots of headers you can increase this value up to 64k (65535).</h1><p>buffer-size=65535</p>
<p>这里以socket形式运行uwsgi，绑定了本地的9090端口，也就是上文nginx配置中uwsgi_pass指定的端口。</p>
<p>大概解释下几个配置的含义：</p>
<p>chdir—-应用加载前chdir到指定目录，一般设置为django的工程根目录<br>touch-reload—-如果修改/碰了指定的文件，那么重载uWSGI<br>module—-加载一个WSGI模块的路径，如果django的话就指向对应的wsgi文件模块<br>buffer-size—-设置请求的最大大小 (排除request-body)，这一般映射到请求头的大小。默认情况下，它是4k。如果你接收到了一个更大的请求 (例如，带有大cookies或者查询字符串)，那么你也许需要增加它。它也是一个安全度量，所以调整为你的应用需要，而不是最大输出。该值如果太小会报错<br>然后使用命令启动uwsgi进程，其中uwsgi.ini为上面内容的配置文件</p>
<p>uwsgi -i uwsgi.ini<br>可以看下日志文件有没有报错，或者看下ps -ef|grep uwsgi进程有没有跑起来。一定要确保进程正常run起来才行</p>
<p>至此，DJANGO已经通过nginx+uwsgi可以访问了</p>
<p>三、配置访问vue<br>其实这里访问编译好的vue静态文件有很多方式，本文主要讲述通过nginx直接访问和通过django路由访问</p>
<p>通过django路由访问<br>其实我们也可以直接通过<a href="http://ip:8080/" target="_blank" rel="noopener">http://ip:8080/</a> 来经由django的路由来访问vue的页面。当然要做到这样要确保以下配置的正确</p>
<p>找到DJANGO_DIR根目录下DJANGO_NAME同名文件夹下urls.py，使用通用视图创建最简单的模板控制器，增加一行路由</p>
<p>vim /test_service/DataLable/DataLable</p>
<p>url(r’^$’, TemplateView.as_view(template_name=”index.html”)),<br>上一步使用了Django的模板系统，所以需要配置一下模板使Django知道从哪里找到index.html。在project目录的settings.py下：</p>
<p>TEMPLATES = [<br>    {‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,<br>     ‘DIRS’: [‘/data/dist’],<br>     ‘APP_DIRS’: True,<br>     ‘OPTIONS’: {‘context_processors’: [<br>                ‘django.template.context_processors.debug’,<br>                ‘django.template.context_processors.request’,<br>                ‘django.contrib.auth.context_processors.auth’,<br>                ‘django.contrib.messages.context_processors.messages’,<br>           ],<br>        },<br>    },<br>]<br>按照上述配置完成后，结合前面配置好的nginx和uwsgi，你已经可以通过<a href="http://ip:8080/" target="_blank" rel="noopener">http://ip:8080/</a> 来访问到对应的vue编译好的VUE_HTML_DIR目录下的index.html了，但是这时候你可能会有其他困扰，比如找不到css样式文件的问，这经常是静态配置有误导致找不到静态文件的问题。</p>
<p>Django通过django.contrib.staticfiles来管理静态文件，首先确保django.contrib.staticfiles已经添加到INSTALLED_APPS。默认都是有的</p>
<p>然后可以在DJANGO的配置文件settings.py中增加以下几个配置：</p>
<p>STATIC_URL = ‘/static/‘<br>STATIC_ROOT = os.path.join(BASE_DIR, “static”)</p>
<h1 id="Add-for-vuejs"><a href="#Add-for-vuejs" class="headerlink" title="Add for vuejs"></a>Add for vuejs</h1><p>STATICFILES_DIRS = [<br>    ‘/data/dist/static’,<br>    # other static folders</p>
<p>]</p>
<p>STATIC_URL对外提供WEB访问时static的URL地址<br>STATIC_ROOT设置绝对路径, 用来保存收集到的静态文件，服务器最终也将从该路径中获取文件进行转发。在collectstatic运行的时候会把STATICFILES_DIRS中的静态文件拷贝到这个目录中,达到从开发环境到生产环节过程中移植静态文件的作用。<br>STATICFILES_DIRS用来配置一些开发环境下生成的静态文件的地址，即编译好的VUE_STATIC_DIR<br>在url.py中添加路由</p>
<p>from django.views.static import server </p>
<p>url(r’^static/(?P<path></path>.*)$’, static.serve,{‘document_root’: settings.STATIC_ROOT}, name=’static’),</p>
<p>配置好以上配置后，编译好的静态文件还在VUE_STATIC_DIR目录下，我们最终要执行下面命令才能把STATICFILES_DIRS中的静态文件拷贝到STATIC_ROOT这个目录中，也就是最终生产环境指定的static的存放目录</p>
<p>python manage.py collectstatic<br>这样你访问django的admin网址<a href="http://ip:8080/admin" target="_blank" rel="noopener">http://ip:8080/admin</a> 时，也不会出现找不到css的问题了</p>
<p>当然这种方式其实是通过django的路由来访问静态文件的，一般的，生产环境不会通过django来转发静态文件，而是通过其他服务器进行转发，比如nginx，apache等</p>
<p>通过nginx直接访问</p>
<p>如果你想直接通过nginx访问对应的前端vue文件，可以重新配置一个server来访问对应的html文件，比如上面已经使用了8080端口，我们可以用默认的80端口来配置个server，其中root可以指向存放index.html文件的路径，/static/路径下的root路径可以指向html对应的存放css和js的static文件夹，如果static就在index.html路径下，不指认也可以。直接修改/etc/nginx.conf即可，里面已经有配置好的80端口的server</p>
<p>配置如下所示</p>
<p>server {<br>        listen       80 default_server;<br>        listen       [::]:80 default_server;<br>        server_name  _;<br>        root         /usr/share/nginx/html;<br>        # Load configuration files for the default server block.<br>        include /etc/nginx/default.d/*.conf;<br>        location / {<br>        root /test_service/dist;<br>        index index.html;<br>        }<br>        error_page 404 /404.html;<br>            location = /40x.html {<br>        }<br>        error_page 500 502 503 504 /50x.html;<br>            location = /50x.html {<br>        }</p>
<p>这样我们可以通过<a href="http://ip:80/" target="_blank" rel="noopener">http://ip:80/</a> 来访问vue编译好的页面，使用<a href="http://ip:8080/" target="_blank" rel="noopener">http://ip:8080/</a> 访问django配置的cgi请求</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/07/04/利用Docker来搭建分布式文件系统FastDfs/">
                利用Docker来搭建分布式文件系统FastDfs
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-07-04</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="在-Docker-上搭建分布式文件管理系统FastDfs"><a href="#在-Docker-上搭建分布式文件管理系统FastDfs" class="headerlink" title="在 Docker 上搭建分布式文件管理系统FastDfs"></a>在 Docker 上搭建分布式文件管理系统FastDfs</h1><p><a href="https://v3u.cn/" target="_blank" rel="noopener">首页</a> - <a href="https://v3u.cn/l_id_4" target="_blank" rel="noopener">Mac &amp; Linux</a> /2019-05-19</p>
<p>​    对于文件存储来说，一般情况下简单的处理就是在Django配置文件中配置存储目录，按照规则对文件进行上传或者下载。</p>
<p>​    实际上，当文件较少的时候，Django是可以应付的过来的。但当文件以海量形式出现的时候，Django就并不是那么好用了，于是Fast DFS应运而出。<br>        FastDFS是一个开源的分布式文件系统，它对文件进行管理，功能包括：文件存储、文件同步、文件访问（文件上传、文件下载）等，解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务，如相册网站、视频网站等等。可以说它就是为互联网而生，为大数据而生的。<br>    FastDFS服务端有两个角色：跟踪器（tracker）和存储节点（storage）。跟踪器主要做调度工作，在访问上起负载均衡的作用。 存储节点存储文件，完成文件管理的所有功能：存储、同步和提供存取接口，FastDFS同时对文件的meta data进行管理。跟踪器和存储节点都可以由多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务。其中跟踪器中的所有服务器都是对等的，可以根据服务器的压力情况随时增加或减少。</p>
<p>​    </p>
<p>​    说人话，为啥要用FastDfs:</p>
<p>​    1 解决海量存储，同时存储容量扩展方便。<br>    2 解决文件内容重复,如果用户上传的文件重复(文件指纹一样)，那么系统只有存储一份数据，值得一提的是，这项技术目前被广泛应用在网盘中。<br>    3 结合Nginx提高网站读取图片的效率。</p>
<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190519/20190519152124_33663.png" alt="img"></p>
<p>​    如果我们从头搭建fastdfs服务器那么就太low了，网上有大把的docker镜像供你选择，所以又到了利用docker优越性的时候了，首先下载fastdfs镜像</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull delron/fastdfs</span><br></pre></td></tr></table></figure>

<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190519/20190519134738_17692.png" alt="img"></p>
<p>区区四百多兆就承载了nginx和fastdfs服务</p>
<p>然后使用docker镜像构建tracker容器（跟踪服务器，起到调度的作用），这里tracker服务将会自动映射到宿主机上</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --network=host --name tracker -v /root:/var/root delron/fastdfs tracker</span><br></pre></td></tr></table></figure>

<p>使用docker镜像构建storage容器（存储服务器，提供容量和备份服务），这里storage容器需要依赖tracker服务，传入你的tracker服务的ip地址，端口默认是22122，ip地址也就是你宿主机的ip</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --network=host --name storage -e TRACKER_SERVER=192.168.99.100:22122 -v /root:/var/root -e GROUP_NAME=group1 delron/fastdfs storage</span><br></pre></td></tr></table></figure>

<p>此时，命令行输入 docker ps 就可以看到两套服务都已经启动</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190519/20190519135541_36259.png" alt="img"></p>
<p>这时，进入正在后台运行的storage容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker exec -it storage /bin/bash</span><br></pre></td></tr></table></figure>

<p>随便下载一张图片,这个不用担心，因为在容器中如果不提交仓库的话，该图片是不会保存的</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://v3u.cn/v3u/Public/images/logo.png</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/bin/fdfs_upload_file /etc/fdfs/client.conf logo.png</span><br></pre></td></tr></table></figure>

<p>这时该图片已上传至文件系统，并在执行该语句后返回图片存储的网络地址</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190519/20190519140239_88245.png" alt="img"></p>
<p>最后通过浏览器访问以下存储在Fastdfs的图片，这张图片是通过nginx代理的静态资源，默认nginx监听8888端口，所以需要加上端口号，如果是在阿里云上部署，则需要暴露外部端口8888</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190519/20190519140507_13422.png" alt="img"></p>
<p>可以看到，没有任何问题，同理，如果是视频资源，同样可以上传到fastdfs中，搞定收工。</p>

        </div>
    

</div>
            
        </section>
    </div>
</div>



    <div class="row">
        <div class="col-sm-12">
            <div class="wrap-pagination">
                <a class="" href="/blog/page/2/">
                    <i class="fa fa-chevron-left" aria-hidden="true"></i>
                </a>
                <a class="" href="/blog/page/4/">
                    <i class="fa fa-chevron-right" aria-hidden="true"></i>
                </a>
            </div>
        </div>
    </div>




</div>

<!-- Footer -->
<div class="push"></div>

<footer class="footer-content">
    <div class="container">
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-6 col-lg-6 footer-about">
                <h2>About</h2>
                <p>
                    This theme was developed by <a href="https://github.com/klugjo">Jonathan Klughertz</a>. The source code is available on Github. Create Websites. Make Magic.
                </p>
            </div>
            
    <div class="col-xs-6 col-sm-6 col-md-3 col-lg-3 recent-posts">
        <h2>Recent Posts</h2>
        <ul>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/25/tars框架环境基础搭建/">tars框架环境基础搭建</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/20/认识tars框架/">认识tars框架</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/05/redis数据迁移备份与恢复/">redis数据迁移备份与恢复</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/09/21/负载均衡的5种策略/">负载均衡的5种策略</a>
            </li>
            
        </ul>
    </div>



            
        </div>
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <ul class="list-inline footer-social-icons">
                    
                    <li class="list-inline-item">
                        <a href="https://github.com/klugjo/hexo-theme-alpha-dust">
                            <span class="footer-icon-container">
                                <i class="fa fa-github"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://twitter.com/?lang=en">
                            <span class="footer-icon-container">
                                <i class="fa fa-twitter"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.facebook.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-facebook"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.instagram.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-instagram"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://dribbble.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-dribbble"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://plus.google.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-google-plus"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.behance.net/">
                            <span class="footer-icon-container">
                                <i class="fa fa-behance"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://500px.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-500px"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="mailto:test@example.com">
                            <span class="footer-icon-container">
                                <i class="fa fa-envelope-o"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="\#">
                            <span class="footer-icon-container">
                                <i class="fa fa-rss"></i>
                            </span>
                        </a>
                    </li>
                    
                </ul>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <div class="footer-copyright">
                    @Untitled. All right reserved | Design & Hexo <a href="http://www.codeblocq.com/">Jonathan Klughertz</a>
                </div>
            </div>
        </div>
    </div>
</footer>

<!-- After footer scripts -->

<!-- jQuery -->
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>

<!-- Tween Max -->
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenMax.min.js"></script>

<!-- Gallery -->
<script src="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.js" type="text/javascript" charset="utf-8"></script>

<!-- Custom JavaScript -->
<script src="/blog/js/main.js"></script>

<!-- Disqus Comments -->



</body>

</html>